package com.googlecode.groovy_toy_orm

import com.googlecode.groovy_toy_orm.framework.BaseFunctionalTest
import groovy.sql.Sql
import groovy.transform.ToString
import org.testng.annotations.Test

import static com.googlecode.groovy_toy_orm.MapperUtil.transform
import static com.googlecode.groovy_toy_orm.MapperUtil.transformBack


/**
 * @author: DavydovMD
 * Date: 05.04.13
 * Time: 14:10
 */

class DbMappersTests extends BaseFunctionalTest {
    final static Sql ourDb
    static {
        Class.forName("org.sqlite.JDBC");
        ourDb = Sql.newInstance("jdbc:sqlite::memory:", 'org.sqlite.SQLite')
        ourDb.withTransaction({
            ourDb.execute("CREATE table student as select 1 as id, 'Ivan                                  ' as first_name, 'Ivanov                                 ' as lastName, 'Graduate               ' as status")
            ourDb.execute("delete from student")
            ourDb.execute("insert into student values(2,'Ivan','Ivanov','Graduate')")
            ourDb.execute("insert into student values(3,'Sidor','Sidorov','Student')")
            ourDb.execute("insert into student values(4,'Looser L.','Looser','Expelled')")
            ourDb.commit()
        })
        int res = ourDb.firstRow("select count(*) from student").values().iterator()?.next() as int
        assert res == 3
    }

    static enum StudentStatus {
        Graduate, Student, Expelled
    }


    @ToString(includeFields = true)
    static class Student {
        /* Fields */
        int id
        String firstName
        String lastName
        StudentStatus status

        /* Mapper */
        static SingleDbTableMapper<Student> mapper =
            new SingleDbTableMapper<Student>(
                    new MapperFields().with() {
                        field("id")
                        field("firstName", "first_name")
                        field("lastName")
                        field("status", "status", transform.stringEnum(StudentStatus.class), transformBack.stringEnum(StudentStatus.class))
                        delegate as MapperFields
                    }
                    , { DbMappersTests.ourDb }
                    , "student"
                    , "id"
                    , Student.class
            )

        /* Provider */
        static BaseProvider<Student> provider = new BaseProvider<Student>(Student.class, [Student.mapper])

        /* Default constructor, required by Provider */

        public Student(Map params) {
            for (Map.Entry entry in params.entrySet()) {
                if (entry.getValue() != null) {
                    this."${entry.getKey()}" = entry.getValue()
                }
            }
        }
    }


    @Test
    public void tableMapperTest() {
        asTest() {
            Student ivanov
            asStep("buildFromDb() with primary key value specified only") {
                ivanov = Student.provider.byId(2)
                assert ivanov.firstName == "Ivan"
                assert ivanov.lastName == "Ivanov"
                assert ivanov.status == StudentStatus.Graduate
            }

            asStep("buildFromDb with custom field") {
                Student looser = Student.provider.byFieldValueFirst("lastName", "Looser")
                assert looser.firstName == "Looser L."
            }
        }
    }

    @Test
    public void queryBuilderTest() {
        def query = Student.provider.query()

        QueryExecutor qe = query.allFields()
                .where("firstName", ConditionOp.EQ, 'Ivan')
                .or('status', ConditionOp.EQ, StudentStatus.Expelled)
                .build()

        List<Student> studentz = Student.provider.usingQuery(qe)
        logger.info "$studentz"
        assert studentz.size()==2
    }

}
